package com.lx.boot.db;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lx.annotation.Note;
import com.lx.entity.Pair;
import com.lx.util.LX;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MpService<M extends MpMapper<T>, T> extends ServiceImpl<M,T> implements CommandLineRunner {
    @Autowired
    protected M baseMapper;

    protected Map<String,TableFieldInfo> fieldInfoMap = new HashMap<>();

    protected TableInfo tableInfo;

    @Override
    public void run(String... args) throws Exception {
        tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
        // 获取实体类对应的数据库字段名
        for (TableFieldInfo fieldInfo : tableInfo.getFieldList()) {
            fieldInfoMap.put(fieldInfo.getProperty(),fieldInfo);
        }
    }

    @Note("检查字段数据是否重复!")
    protected void checkUnique(T entity, String fieldProperty) {
        checkUnique(entity, fieldProperty, null);
    }
    @Note("检查字段数据是否重复!")
    protected void checkUnique(T entity, String fieldProperty, String msg) {
        if (fieldInfoMap.containsKey(fieldProperty)){
            Pair<TableFieldInfo, Object> field = getFieldValue(entity, fieldProperty);
            LX.exObj(field, fieldProperty+"字段不存在!");
            QueryWrapper<T> queryWrapper = new QueryWrapper<>();
            try {
                queryWrapper.eq(field.getKey().getColumn(),field.getValue());
                Pair<TableFieldInfo, Object> key = getKeyValue(entity);
                if (LX.isNotEmpty(key) && LX.isNotEmpty(key.getValue())){ // 主键存在
                    queryWrapper.ne(key.getKey().getColumn(),key.getValue()); //如果是新增 过滤主键
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            List<T> res = baseMapper.selectList(queryWrapper);
            if (res.size()>0){ // 已存在
                if (LX.isEmpty(msg)){
                    Schema annotation = field.getKey().getField().getAnnotation(Schema.class);
                    if (annotation == null){
                        msg = "["+fieldProperty+"]已存在!";
                    }else{
                        msg = "["+annotation.description()+"]已存在!";
                    }
                }
                LX.exMsg(msg);
            }
        }
    }

    @Note("获取主键的字段名和值")
    protected Pair<TableFieldInfo, Object> getKeyValue(Object entity){
        String keyProperty = tableInfo.getKeyProperty();
        if (keyProperty != null){ // 存在主键配置
            TableFieldInfo keyFieldInfo = fieldInfoMap.get(keyProperty);
            if (keyFieldInfo != null){
                return new Pair(keyFieldInfo.getColumn(), getFieldValue(entity, keyFieldInfo));
            }
        }
        return null;
    }

    @Note("获取实体中指定参数的值")
    private Pair<TableFieldInfo, Object> getFieldValue(Object entity,String fieldProperty){
        TableFieldInfo fieldInfo = fieldInfoMap.get(fieldProperty);
        if (fieldInfo == null){
            return null;
        }
        return new Pair(fieldInfo.getColumn(),getFieldValue(entity,fieldInfo));
    }

    @Note("获取实体中指定参数的值")
    private Object getFieldValue(Object entity,TableFieldInfo fieldInfo){
        try {
            Field field = fieldInfo.getField();
            field.setAccessible(true);
            return field.get(entity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


}
